<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>Vue面试题 | 破破的QQ空间</title><meta name="author" content="破破"><meta name="copyright" content="破破"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="你对 MVVM 的了解，以及跟 MVC 的区别M V VM 是 Model-View-ViewModel，MVC 是 Model-View-Controller 的缩写，controller 是控制器的意思，MVVM 是 MVC 的变种 生命周期 beforCreate 实例创建之前 created 实例创建之后 beforeMount 实例挂载之前 mounted 实例挂载之后 beforeUp">
<meta property="og:type" content="article">
<meta property="og:title" content="Vue面试题">
<meta property="og:url" content="https://leiboy.gitee.io/blog/2020/03/12/Vue%E9%9D%A2%E8%AF%95%E9%A2%98/index.html">
<meta property="og:site_name" content="破破的QQ空间">
<meta property="og:description" content="你对 MVVM 的了解，以及跟 MVC 的区别M V VM 是 Model-View-ViewModel，MVC 是 Model-View-Controller 的缩写，controller 是控制器的意思，MVVM 是 MVC 的变种 生命周期 beforCreate 实例创建之前 created 实例创建之后 beforeMount 实例挂载之前 mounted 实例挂载之后 beforeUp">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://leiboy.gitee.io/blog/2020/03/12/Vue%E9%9D%A2%E8%AF%95%E9%A2%98/Vue.png">
<meta property="article:published_time" content="2020-03-12T06:48:27.000Z">
<meta property="article:modified_time" content="2024-07-01T14:13:29.125Z">
<meta property="article:author" content="破破">
<meta property="article:tag" content="Vue">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://leiboy.gitee.io/blog/2020/03/12/Vue%E9%9D%A2%E8%AF%95%E9%A2%98/Vue.png"><link rel="shortcut icon" href="/blog/img/favicon.png"><link rel="canonical" href="https://leiboy.gitee.io/blog/2020/03/12/Vue%E9%9D%A2%E8%AF%95%E9%A2%98/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/blog/css/index.css?v=4.14.0-b3"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.1/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.35/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>(()=>{
      const saveToLocal = {
        set: (key, value, ttl) => {
          if (ttl === 0) return
          const now = Date.now()
          const expiry = now + ttl * 86400000
          const item = {
            value,
            expiry
          }
          localStorage.setItem(key, JSON.stringify(item))
        },
      
        get: key => {
          const itemStr = localStorage.getItem(key)
      
          if (!itemStr) {
            return undefined
          }
          const item = JSON.parse(itemStr)
          const now = Date.now()
      
          if (now > item.expiry) {
            localStorage.removeItem(key)
            return undefined
          }
          return item.value
        }
      }
      
      window.btf = {
        saveToLocal: saveToLocal,
        getScript: (url, attr = {}) => new Promise((resolve, reject) => {
          const script = document.createElement('script')
          script.src = url
          script.async = true
          script.onerror = reject
          script.onload = script.onreadystatechange = function() {
            const loadState = this.readyState
            if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
            script.onload = script.onreadystatechange = null
            resolve()
          }

          Object.keys(attr).forEach(key => {
            script.setAttribute(key, attr[key])
          })

          document.head.appendChild(script)
        }),

        getCSS: (url, id = false) => new Promise((resolve, reject) => {
          const link = document.createElement('link')
          link.rel = 'stylesheet'
          link.href = url
          if (id) link.id = id
          link.onerror = reject
          link.onload = link.onreadystatechange = function() {
            const loadState = this.readyState
            if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
            link.onload = link.onreadystatechange = null
            resolve()
          }
          document.head.appendChild(link)
        }),

        addGlobalFn: (key, fn, name = false, parent = window) => {
          const pjaxEnable = false
          if (!pjaxEnable && key.startsWith('pjax')) return

          const globalFn = parent.globalFn || {}
          const keyObj = globalFn[key] || {}
    
          if (name && keyObj[name]) return
    
          name = name || Object.keys(keyObj).length
          keyObj[name] = fn
          globalFn[key] = keyObj
          parent.globalFn = globalFn
        }
      }
    
      const activateDarkMode = () => {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      const activateLightMode = () => {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }

      btf.activateDarkMode = activateDarkMode
      btf.activateLightMode = activateLightMode
      
      const t = saveToLocal.get('theme')
    
        if (t === 'dark') activateDarkMode()
        else if (t === 'light') activateLightMode()
      
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
      const detectApple = () => {
        if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
          document.documentElement.classList.add('apple')
        }
      }
      detectApple()
    })()</script><script>const GLOBAL_CONFIG = {
  root: '/blog/',
  algolia: undefined,
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false,"highlightFullpage":true,"highlightMacStyle":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  dateSuffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  infinitegrid: {
    js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid@4.11.1/dist/infinitegrid.min.js',
    buttonText: '加载更多'
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isAnchor: false,
  percent: {
    toc: true,
    rightside: false,
  },
  autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'Vue面试题',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2024-07-01 22:13:29'
}</script><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">10</div></a><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">7</div></a><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">2</div></a></div><hr class="custom-hr"/></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('/blog/2020/03/12/Vue%E9%9D%A2%E8%AF%95%E9%A2%98/Vue.png')"><nav id="nav"><span id="blog-info"><a href="/blog/" title="破破的QQ空间"><span class="site-name">破破的QQ空间</span></a></span><div id="menus"><div id="toggle-menu"><span class="site-page"><i class="fas fa-bars fa-fw"></i></span></div></div></nav><div id="post-info"><h1 class="post-title">Vue面试题</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2020-03-12T06:48:27.000Z" title="发表于 2020-03-12 14:48:27">2020-03-12</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-07-01T14:13:29.125Z" title="更新于 2024-07-01 22:13:29">2024-07-01</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/blog/categories/%E9%9D%A2%E8%AF%95%E9%A2%98/">面试题</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="Vue面试题"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h4 id="你对-MVVM-的了解，以及跟-MVC-的区别"><a href="#你对-MVVM-的了解，以及跟-MVC-的区别" class="headerlink" title="你对 MVVM 的了解，以及跟 MVC 的区别"></a>你对 MVVM 的了解，以及跟 MVC 的区别</h4><p>M V VM 是 Model-View-ViewModel，MVC 是 Model-View-Controller 的缩写，controller 是控制器的意思，MVVM 是 MVC 的变种</p>
<h4 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h4><ul>
<li>beforCreate 实例创建之前</li>
<li>created 实例创建之后</li>
<li>beforeMount 实例挂载之前</li>
<li>mounted 实例挂载之后</li>
<li>beforeUpdate 实例更新前</li>
<li>updated 实例更新后</li>
<li>beforeDestory</li>
<li>destoryed</li>
<li>keep-alive 中的 actived 路由访问此组件时</li>
<li>keep-alive 中的 deactived 路由访问此组件时</li>
</ul>
<h4 id="v-if-和-v-show-的区别"><a href="#v-if-和-v-show-的区别" class="headerlink" title="v-if 和 v-show 的区别"></a>v-if 和 v-show 的区别</h4><ul>
<li>v-if 是通过条件渲染或不渲染</li>
<li>v-show 是通过条件更改 display 属性为 none 或 block；频繁操作一般使用 v-show</li>
</ul>
<h4 id="css-只在当前组件中起作用"><a href="#css-只在当前组件中起作用" class="headerlink" title="css 只在当前组件中起作用"></a>css 只在当前组件中起作用</h4><p>style 标签加 scoped 属性</p>
<h4 id="vue-中-key-值的作用-key能不能用index"><a href="#vue-中-key-值的作用-key能不能用index" class="headerlink" title="vue 中 key 值的作用?  key能不能用index?"></a>vue 中 key 值的作用?  key能不能用index?</h4><p>如果在 v-for 遍历中不加 key 值，vue 会采用“就地复用”。</p>
<h4 id="watch-和-computed-的区别"><a href="#watch-和-computed-的区别" class="headerlink" title="watch 和 computed 的区别"></a>watch 和 computed 的区别</h4><ul>
<li>watch<ul>
<li>不支持缓存，数据变，直接触发</li>
<li>支持异步</li>
<li>监听的数据必须已经定义</li>
</ul>
</li>
<li>computed<ul>
<li>支持缓存，依赖数据改变才会重新触发计算</li>
<li>不支持异步，当内部有异步操作时，则无效</li>
</ul>
</li>
</ul>
<h4 id="keep-alive"><a href="#keep-alive" class="headerlink" title="keep-alive"></a>keep-alive</h4><p>内置组件，可以缓存被包裹的组件状态</p>
<h4 id="怎么让部分组件缓存，部分组件不缓存"><a href="#怎么让部分组件缓存，部分组件不缓存" class="headerlink" title="怎么让部分组件缓存，部分组件不缓存"></a>怎么让部分组件缓存，部分组件不缓存</h4><ul>
<li>include 包含的组件</li>
<li>exclude 排除的组件</li>
<li>max 缓存组件最大值<blockquote>
<p>也可以搭配路由使用 meta 中设置参数，然后组件判断当前路由中是否有这个参数</p>
</blockquote>
</li>
</ul>
<h4 id="Vue-实现双向数据绑定的原理"><a href="#Vue-实现双向数据绑定的原理" class="headerlink" title="Vue 实现双向数据绑定的原理"></a>Vue 实现双向数据绑定的原理</h4><blockquote>
<p>采用数据劫持配合发布者-订阅者模式实现的</p>
</blockquote>
<ul>
<li>vue2 中使用 Object.defineProperty 来劫持各个属性的 getter 和 setter，当劫持到数据变化时，将变化传给 setter，然后执行相应的回调</li>
<li>vue3 中使用的是 Proxy 实现。</li>
</ul>
<h4 id="Proxy-的优点缺点"><a href="#Proxy-的优点缺点" class="headerlink" title="Proxy 的优点缺点"></a>Proxy 的优点缺点</h4><ul>
<li>可以监听数组的变化</li>
<li>可以直接监听对象，而不是监听属性</li>
<li>劣势是兼容较差</li>
</ul>
<h4 id="父子组件传参"><a href="#父子组件传参" class="headerlink" title="父子组件传参"></a>父子组件传参</h4><ul>
<li>父传子: 用绑定属性的方式将所需要传递的参数绑定到子组件上，然后子组件中通过或 props，接收参数，从而可以直接使用。props 可以设置参数类型、否为必传、默认值等</li>
<li>子传父: 通过$emit 方法，调用父组件的方法，方法中携带要传递的参数，父组间方法被执行，拿到参数</li>
</ul>
<h4 id="兄弟组件传参"><a href="#兄弟组件传参" class="headerlink" title="兄弟组件传参"></a>兄弟组件传参</h4><ul>
<li><p>eventBus 相当于创建一个实践中心，用他来传递和接收参数，项目较小时适合使用</p>
<ul>
<li>new 一个新的 vue 实例 eventbus A 组件传值时触发 eventbus.$emit 方法携带参数</li>
<li>B 组件触发 eventbus.$on方法，触发以上事件，拿到传递的值（$on 用完必须$off）</li>
</ul>
</li>
<li><p>vuex 状态管理</p>
</li>
</ul>
<h4 id="vue-路由-hash-模式和-history-模式"><a href="#vue-路由-hash-模式和-history-模式" class="headerlink" title="vue 路由 hash 模式和 history 模式"></a>vue 路由 hash 模式和 history 模式</h4><ul>
<li>hash: 在浏览器 url 中显示#，#后边为 hash 值，使用 hash 模式，hash 虽然包含在 url 中，但不配包含在 http 请求中；后端不用单独再去相应配置</li>
<li>history: 采用 h5 的新特性，提供了两个新方法 pushState()和 replaceState()可以对浏览器路由栈进行修改，以及 popState 时间监听到变化 - replace() 进入新页面，关闭旧页面（不能返<br>回） - push() 进入相应页面，保留上个页面（可返回）</li>
</ul>
<h4 id="路由守卫"><a href="#路由守卫" class="headerlink" title="路由守卫"></a>路由守卫</h4><ul>
<li>全局钩子<ul>
<li>router.beforeEach 前置</li>
<li>router.BeforeResolve(2.5 新增，解析守卫)</li>
<li>router.afterEach 后置</li>
</ul>
</li>
<li>组件内钩子<ul>
<li>beforeRouteEnter 渲染时</li>
<li>beforeRouteUpdate 更新时</li>
<li>beforeRouteLeave 离开时</li>
</ul>
</li>
<li>路由独享钩子（在路由列表中调用）<ul>
<li>beforEnter</li>
</ul>
</li>
</ul>
<h4 id="路由传参"><a href="#路由传参" class="headerlink" title="路由传参"></a>路由传参</h4><ul>
<li>params 刷新参数会消失</li>
<li>query 参数展示在 url 中，刷新之后依然存在</li>
</ul>
<h4 id="Vuex（状态存储）"><a href="#Vuex（状态存储）" class="headerlink" title="Vuex（状态存储）"></a>Vuex（状态存储）</h4><ul>
<li>state 状态数据集，不可以直接修改 state 中的数据</li>
<li>mutations 相当于组件中的 methods（方法集），用于改变 state 中的数据</li>
<li>getters 相当于组件中的 compunted,当需要对 state 中的数据进行操作返回一个值的时候，可以使用它</li>
<li>actions 主要用来存储异步操作</li>
<li>modules 项目较复杂时，使用它来分模块</li>
</ul>
<h4 id="vue-自定义指令-directive"><a href="#vue-自定义指令-directive" class="headerlink" title="vue 自定义指令 directive"></a>vue 自定义指令 directive</h4><ul>
<li><p>接收一个对象</p>
</li>
<li><p>钩子</p>
<ul>
<li>bind 指令被绑定到元素上时调用，只调用一次</li>
<li>inserted 当组件被绑定到父节点的时候调用</li>
<li>upadte 所在组件更新时调用</li>
</ul>
</li>
<li><p>钩子函数的参数</p>
<ul>
<li>el DOM 元素</li>
<li>binding 包含指令名 name、指令绑定之 value 等</li>
<li>vNode 虚拟 DOM 节点</li>
</ul>
</li>
</ul>
<h4 id="vue-过滤器-filter"><a href="#vue-过滤器-filter" class="headerlink" title="vue 过滤器 filter"></a>vue 过滤器 filter</h4><p>定义过滤器返回一个值，第一个参数为默认值，第二个参数之后为传入的值，组件上以管道符 | 定义</p>
<h4 id="mixin-注入"><a href="#mixin-注入" class="headerlink" title="mixin 注入"></a>mixin 注入</h4><p>用来分发组件中可混用的功能全局混入时，会影响每个组件的实例，全局混入后，可以通过 this.变量拿到参数</p>
<h4 id="nextTick"><a href="#nextTick" class="headerlink" title="nextTick"></a>nextTick</h4><p>在下次 DOM 更新循环之后执行延迟回调</p>
<h4 id="虚拟-DOM"><a href="#虚拟-DOM" class="headerlink" title="虚拟 DOM"></a>虚拟 DOM</h4><blockquote>
<p>一个能代表 DOM 树的对象，通常含有标签名、便签上的属性、事件监听和子元素，以及其他属性</p>
</blockquote>
<ul>
<li>优点<ul>
<li>能减少不必要的 DOM 操作</li>
<li>能跨平台渲染，如 ios 安卓 小程序</li>
</ul>
</li>
<li>缺点<ul>
<li>需要额外的创建函数如 react 中的 createElement 或者 Vue 中的 h，但是可以通过 jsx 语法或者 vue 的模板语法简化成 html 的写法</li>
</ul>
</li>
</ul>
<h4 id="父子孙组件传参"><a href="#父子孙组件传参" class="headerlink" title="父子孙组件传参"></a>父子孙组件传参</h4><p>$attrs以及$listeners</p>
<h4 id="子组件调用父组件方法-不用属性绑定的方式怎么实现"><a href="#子组件调用父组件方法-不用属性绑定的方式怎么实现" class="headerlink" title="子组件调用父组件方法 不用属性绑定的方式怎么实现"></a>子组件调用父组件方法 不用属性绑定的方式怎么实现</h4><p>直接在子组件中通过 this.$parent.event 来调用父组件的方法</p>
<h4 id="动态绑定事件"><a href="#动态绑定事件" class="headerlink" title="动态绑定事件"></a>动态绑定事件</h4><p>事件委托的方式</p>
<h4 id="vue-打包多页面-优化首屏加载"><a href="#vue-打包多页面-优化首屏加载" class="headerlink" title="vue 打包多页面 优化首屏加载"></a>vue 打包多页面 优化首屏加载</h4><ul>
<li>路由采用懒加载</li>
<li>不生成 map 文件</li>
<li>找到 config&#x2F;index.js，修改为 productionSourceMap: false</li>
<li>vue 组件尽量不要全局引入</li>
<li>开启 gzip 压缩</li>
<li>服务端渲染</li>
</ul>
<h4 id="axios-的封装"><a href="#axios-的封装" class="headerlink" title="axios 的封装"></a>axios 的封装</h4><p>使用 promise 做二次封装，添加拦截器，请求头带上 token 响应状态判断。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&quot;axios&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">NProgress</span> <span class="keyword">from</span> <span class="string">&quot;nprogress&quot;</span>; <span class="comment">// 引入nprogress插件</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;nprogress/nprogress.css&quot;</span>; <span class="comment">// 这个nprogress样式必须引入</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="variable constant_">BASE_URL</span>, <span class="variable constant_">TIMEOUT</span> &#125; <span class="keyword">from</span> <span class="string">&quot;./config&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> instance = axios.<span class="title function_">create</span>(&#123;</span><br><span class="line">  <span class="attr">baseURL</span>: <span class="variable constant_">BASE_URL</span>,</span><br><span class="line">  <span class="attr">timeout</span>: <span class="variable constant_">TIMEOUT</span>,</span><br><span class="line">&#125;);</span><br><span class="line">axios.<span class="property">defaults</span>.<span class="property">headers</span>[<span class="string">&quot;Content-Type&quot;</span>] = <span class="string">&quot;application/json&quot;</span>; <span class="comment">//设置默认提交 json</span></span><br><span class="line">axios.<span class="property">defaults</span>.<span class="property">transformRequest</span> = <span class="function">(<span class="params">data</span>) =&gt;</span> <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(data); <span class="comment">//把数据对象序列化成 json字符串</span></span><br><span class="line"></span><br><span class="line">instance.<span class="property">interceptors</span>.<span class="property">request</span>.<span class="title function_">use</span>(</span><br><span class="line">  <span class="function">(<span class="params">config</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="title class_">NProgress</span>.<span class="title function_">start</span>(); <span class="comment">// 设置加载进度条(开始..)</span></span><br><span class="line">    <span class="comment">// 1.发送网络请求时, 在界面的中间位置显示Loading的组件</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2.某一些请求要求用户必须携带token, 如果没有携带, 那么直接跳转到登录页面</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 3.params/data序列化的操作</span></span><br><span class="line">    <span class="keyword">return</span> config;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="function">(<span class="params">err</span>) =&gt;</span> &#123;&#125;</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">instance.<span class="property">interceptors</span>.<span class="property">response</span>.<span class="title function_">use</span>(</span><br><span class="line">  <span class="function">(<span class="params">res</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="title class_">NProgress</span>.<span class="title function_">done</span>(); <span class="comment">// 设置加载进度条(结束..)</span></span><br><span class="line">    <span class="keyword">return</span> res.<span class="property">data</span>;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="function">(<span class="params">err</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (err &amp;&amp; err.<span class="property">response</span>) &#123;</span><br><span class="line">      <span class="keyword">switch</span> (err.<span class="property">response</span>.<span class="property">status</span>) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">400</span>:</span><br><span class="line">          <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;请求错误&quot;</span>);</span><br><span class="line">          <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">401</span>:</span><br><span class="line">          <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;未授权访问&quot;</span>);</span><br><span class="line">          <span class="keyword">break</span>;</span><br><span class="line">        <span class="attr">default</span>:</span><br><span class="line">          <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;其他错误信息&quot;</span>);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> err;</span><br><span class="line">  &#125;</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> instance;</span><br></pre></td></tr></table></figure>

<h4 id="vue-router-动态路由"><a href="#vue-router-动态路由" class="headerlink" title="vue-router 动态路由"></a>vue-router 动态路由</h4><p>在 router 目录下的 index.js 文件下，对 path 属性加上&#x2F;：id。使用 router 对象的 params.id</p>
<h4 id="插槽-slot"><a href="#插槽-slot" class="headerlink" title="插槽 slot"></a>插槽 slot</h4><p>组件封装时，可通过插槽 slot 设置占位，调用时直接将插槽内容添加到相应位置</p>
<h4 id="vue-组件更新之后如何获取最新-DOM"><a href="#vue-组件更新之后如何获取最新-DOM" class="headerlink" title="vue 组件更新之后如何获取最新 DOM"></a>vue 组件更新之后如何获取最新 DOM</h4><p>在修改数据后调用 this.$nextTick，首次加载在mounted函数里面调用this.$nextTick</p>
<h4 id="vue-动态组件是什么"><a href="#vue-动态组件是什么" class="headerlink" title="vue 动态组件是什么"></a>vue 动态组件是什么</h4><p>让多个组件使用同一个挂载点，并动态切换，这就是动态组件</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;home&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">component</span> <span class="attr">:is</span>=<span class="string">&quot;currentComponent&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">component</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">  <span class="keyword">import</span> <span class="title class_">Tab0</span> <span class="keyword">from</span> <span class="string">&quot;@/components/Tab0.vue&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">  <span class="keyword">import</span> <span class="title class_">Tab1</span> <span class="keyword">from</span> <span class="string">&quot;@/components/Tab1.vue&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">  <span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">data</span>: <span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">currentIndex</span>: <span class="number">0</span> <span class="comment">// 通过改变currentIndex改变要挂载的组件名</span></span></span><br><span class="line"><span class="language-javascript">          &#125;</span></span><br><span class="line"><span class="language-javascript">      &#125;,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">components</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="string">&quot;tab-0&quot;</span>: <span class="title class_">Tab0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="string">&quot;tab-1&quot;</span>: <span class="title class_">Tab1</span></span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">      <span class="title function_">currentComponent</span>(<span class="params"></span>) &#123; <span class="comment">// 动态计算要挂载的组件的组件名</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">return</span> <span class="string">`tab-<span class="subst">$&#123;<span class="variable language_">this</span>.currentIndex&#125;</span>`</span>; <span class="comment">// &quot;tab-0&quot; 、&quot;tab-1&quot;</span></span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">  &#125;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="vue-如何异步加载组件"><a href="#vue-如何异步加载组件" class="headerlink" title="vue 如何异步加载组件"></a>vue 如何异步加载组件</h4><p>什么时候用什么时候加载</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">components</span>:&#123;</span><br><span class="line">   abc：（）=&gt; <span class="keyword">import</span>(../../abc.<span class="property">vue</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="vue-如何缓存组件"><a href="#vue-如何缓存组件" class="headerlink" title="vue 如何缓存组件"></a>vue 如何缓存组件</h4><p>keep-alive</p>
<h4 id="vue-组件如何抽离公共逻辑"><a href="#vue-组件如何抽离公共逻辑" class="headerlink" title="vue 组件如何抽离公共逻辑"></a>vue 组件如何抽离公共逻辑</h4><p>mixin</p>
<h4 id="vue-是如何监听数组变化的"><a href="#vue-是如何监听数组变化的" class="headerlink" title="vue 是如何监听数组变化的"></a>vue 是如何监听数组变化的</h4><p>vue 重写了数组的 push、splice、pop 等方法。</p>
<h4 id="虚拟-DOM-diff-算法"><a href="#虚拟-DOM-diff-算法" class="headerlink" title="虚拟 DOM diff 算法"></a>虚拟 DOM diff 算法</h4><p>虚拟 dom 相当于在 JS 和真实 dom 中间加了一个缓存，利用 diff 算法避免了没有必要的 dom 操作，从而提高性能。</p>
<h4 id="vue-组件是如何渲染和更新的"><a href="#vue-组件是如何渲染和更新的" class="headerlink" title="vue 组件是如何渲染和更新的"></a>vue 组件是如何渲染和更新的</h4><p>vue 组件初次渲染过程</p>
<ul>
<li>解析模板为 render 函数</li>
<li>触发响应式，监听 data 属性的 getter 和 setter</li>
<li>执行 render 函数， 生成 vnode，patch(elem,vnode)</li>
</ul>
<p>vue 组件更新过程</p>
<ul>
<li>修改 data， 触发 setter （此前在 getter 中已被监听）</li>
<li>重新执行 render 函数，生成 newVnode</li>
<li>patch(vnode, newVnode)</li>
</ul>
<h4 id="v-for-为何使用-key"><a href="#v-for-为何使用-key" class="headerlink" title="v-for 为何使用 key"></a>v-for 为何使用 key</h4><p>如果在 v-for 遍历中不加 key 值，vue 会采用“就地复用”。</p>
<h4 id="组件-data-为何是函数"><a href="#组件-data-为何是函数" class="headerlink" title="组件 data 为何是函数"></a>组件 data 为何是函数</h4><p>组件中的 data 写成一个函数，数据以函数返回值形式定义，这样每复用一次组件，就会返回一份新的 data，类似于给每个组件实例创建一个私有的数据空间，让各个组件实例维护各自的数据。而单纯的写成对象形式，就使得所有组件实例共用了一份 data，就会造成一个变了全都会变的结果。</p>
<h4 id="何时使用-keep-alive"><a href="#何时使用-keep-alive" class="headerlink" title="何时使用 keep-alive"></a>何时使用 keep-alive</h4><ul>
<li>缓存组件，不需要重复渲染</li>
<li>优化性能</li>
</ul>
<h4 id="何时需要使用-beforeDestroy"><a href="#何时需要使用-beforeDestroy" class="headerlink" title="何时需要使用 beforeDestroy"></a>何时需要使用 beforeDestroy</h4><p>页面卸载需要清除的时间绑定 定时器 以及初始化数据等</p>
<h4 id="使用-this-obj-给-data-中新加入一个属性，这个数据是响应式的么？为什么？"><a href="#使用-this-obj-给-data-中新加入一个属性，这个数据是响应式的么？为什么？" class="headerlink" title="使用 this.obj&#x3D;{} 给 data 中新加入一个属性，这个数据是响应式的么？为什么？"></a>使用 this.obj&#x3D;{} 给 data 中新加入一个属性，这个数据是响应式的么？为什么？</h4><p>不是响应式数据。</p>
<p>响应式对象和响应式数组是指在 vue 初始化时期，利用 Object.defineProperty()方法对其进行监听，这样在修改数据时会及时体现在页面上。</p>
<p>可以使用$set 方法</p>
<h4 id="delete-和-Vue-delete-删除数组的区别"><a href="#delete-和-Vue-delete-删除数组的区别" class="headerlink" title="delete 和 Vue.delete 删除数组的区别"></a>delete 和 Vue.delete 删除数组的区别</h4><p>delete 只是被删除的元素变成了 empty&#x2F;undefined 其他的元素的键值还是不变。</p>
<p>Vue.delete 直接删除了数组 改变了数组的键值。</p>
<h4 id="如何优化-SPA-应用的首屏加载速度慢的问题？"><a href="#如何优化-SPA-应用的首屏加载速度慢的问题？" class="headerlink" title="如何优化 SPA 应用的首屏加载速度慢的问题？"></a>如何优化 SPA 应用的首屏加载速度慢的问题？</h4><ul>
<li>将公用的 JS 库通过 script 标签外部引入，减小 app.bundel 的大小，让浏览器并行下载资源文件，提高下载速度；</li>
<li>在配置 路由时，页面和组件使用懒加载的方式引入，进一步缩小 app.bundel 的体积，在调用某个组件时再加载对应的 js 文件；</li>
<li>加一个首屏 loading 图，提升用户体验；</li>
</ul>
<h4 id="前端如何优化网站性能"><a href="#前端如何优化网站性能" class="headerlink" title="前端如何优化网站性能"></a>前端如何优化网站性能</h4><ul>
<li>减少 HTTP 请求数量</li>
<li>CSS Sprites</li>
<li>合并 CSS 和 JS 文件</li>
<li>采用 lazyLoad</li>
<li>控制资源文件加载优先级</li>
<li>利用浏览器缓存</li>
<li>减少重排（Reflow）</li>
<li>减少 DOM 操作</li>
<li>图标使用 IconFont 替换</li>
</ul>
<h4 id="query-和-params-的区别"><a href="#query-和-params-的区别" class="headerlink" title="query 和 params 的区别"></a>query 和 params 的区别</h4><ul>
<li>query 要用 path 来引入，params 要用 name 来引入，</li>
<li>接收参数时，分别是 this.$route.query.name和this.$route.params.name（注意：是$route而不是$router）。</li>
<li>query 更加类似于我们 ajax 中 get 传参，params 则类似于 post，前者在浏览器的地址栏中显示，params 不显示</li>
<li>params 传值一刷新就没了，query 传值刷新还存在</li>
</ul>
<h4 id="SPA-单页面，有什么优缺点？"><a href="#SPA-单页面，有什么优缺点？" class="headerlink" title="SPA 单页面，有什么优缺点？"></a>SPA 单页面，有什么优缺点？</h4><p>SPA（ single-page application ）仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成，SPA 不会因为用户的操作而进行页面的重新加载或跳转；取而代之的是利用路由机制实现 HTML 内容的变换，UI 与用户的交互，避免页面的重新加载。</p>
<p><strong>优点：</strong></p>
<ul>
<li><p>良好的交互体验</p>
</li>
<li><p>良好的前后端工作分离模式</p>
</li>
<li><p>减轻服务器压力</p>
</li>
</ul>
<p><strong>缺点：</strong></p>
<ul>
<li>首屏加载慢 解决方案：Vue-router 懒加载、使用 CDN 加速、异步加载组件、服务端渲染</li>
<li>不利于 SEO 解决方案：服务端渲染、页面预渲染、路由采用 h5 history 模式</li>
</ul>
<h4 id="聊聊你对-Vue-js-的-template-编译的理解？"><a href="#聊聊你对-Vue-js-的-template-编译的理解？" class="headerlink" title="聊聊你对 Vue.js 的 template 编译的理解？"></a>聊聊你对 Vue.js 的 template 编译的理解？</h4><p>简而言之，就是先转化成 AST 树，再得到的 render 函数返回 VNode（Vue 的虚拟 DOM 节点）</p>
<h4 id="第一次页面加载会触发哪几个生命周期？"><a href="#第一次页面加载会触发哪几个生命周期？" class="headerlink" title="第一次页面加载会触发哪几个生命周期？"></a>第一次页面加载会触发哪几个生命周期？</h4><p>beforeCreate, created, beforeMount, mounted</p>
<h4 id="为什么会出现-vue-修改数据后页面没有刷新这个问题？如何解决？"><a href="#为什么会出现-vue-修改数据后页面没有刷新这个问题？如何解决？" class="headerlink" title="为什么会出现 vue 修改数据后页面没有刷新这个问题？如何解决？"></a>为什么会出现 vue 修改数据后页面没有刷新这个问题？如何解决？</h4><p>如 Vue 不能检测通过数组索引直接修改一个数组项<br>数组改变后重新赋值 或着使用文档推荐的 vue 重写过的数组操作方法，或者 set</p>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta"><i class="fas fa-circle-user fa-fw"></i>文章作者: </span><span class="post-copyright-info"><a href="https://leiboy.gitee.io/blog">破破</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta"><i class="fas fa-square-arrow-up-right fa-fw"></i>文章链接: </span><span class="post-copyright-info"><a href="https://leiboy.gitee.io/blog/2020/03/12/Vue%E9%9D%A2%E8%AF%95%E9%A2%98/">https://leiboy.gitee.io/blog/2020/03/12/Vue%E9%9D%A2%E8%AF%95%E9%A2%98/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta"><i class="fas fa-circle-exclamation fa-fw"></i>版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://leiboy.gitee.io/blog" target="_blank">破破的QQ空间</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/blog/tags/Vue/">Vue</a></div><div class="post_share"><div class="social-share" data-image="/blog/2020/03/12/Vue%E9%9D%A2%E8%AF%95%E9%A2%98/Vue.png" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.3/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.3/sharejs/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-full"><a href="/blog/2022/04/02/React%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E8%A1%A8%E5%8D%95%E5%AE%9E%E7%8E%B0/" title="React中的动态表单实现"><img class="cover" src="/blog/2022/04/02/React%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E8%A1%A8%E5%8D%95%E5%AE%9E%E7%8E%B0/react-logo.png" onerror="onerror=null;src='/blog/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">React中的动态表单实现</div></div></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="this.onerror=null;this.src='/blog/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">破破</div><div class="author-info__description"></div></div><div class="card-info-data site-data is-center"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">10</div></a><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">7</div></a><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">2</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%A0%E5%AF%B9-MVVM-%E7%9A%84%E4%BA%86%E8%A7%A3%EF%BC%8C%E4%BB%A5%E5%8F%8A%E8%B7%9F-MVC-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="toc-number">1.</span> <span class="toc-text">你对 MVVM 的了解，以及跟 MVC 的区别</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="toc-number">2.</span> <span class="toc-text">生命周期</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#v-if-%E5%92%8C-v-show-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="toc-number">3.</span> <span class="toc-text">v-if 和 v-show 的区别</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#css-%E5%8F%AA%E5%9C%A8%E5%BD%93%E5%89%8D%E7%BB%84%E4%BB%B6%E4%B8%AD%E8%B5%B7%E4%BD%9C%E7%94%A8"><span class="toc-number">4.</span> <span class="toc-text">css 只在当前组件中起作用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E4%B8%AD-key-%E5%80%BC%E7%9A%84%E4%BD%9C%E7%94%A8-key%E8%83%BD%E4%B8%8D%E8%83%BD%E7%94%A8index"><span class="toc-number">5.</span> <span class="toc-text">vue 中 key 值的作用?  key能不能用index?</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#watch-%E5%92%8C-computed-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="toc-number">6.</span> <span class="toc-text">watch 和 computed 的区别</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#keep-alive"><span class="toc-number">7.</span> <span class="toc-text">keep-alive</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%80%8E%E4%B9%88%E8%AE%A9%E9%83%A8%E5%88%86%E7%BB%84%E4%BB%B6%E7%BC%93%E5%AD%98%EF%BC%8C%E9%83%A8%E5%88%86%E7%BB%84%E4%BB%B6%E4%B8%8D%E7%BC%93%E5%AD%98"><span class="toc-number">8.</span> <span class="toc-text">怎么让部分组件缓存，部分组件不缓存</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Vue-%E5%AE%9E%E7%8E%B0%E5%8F%8C%E5%90%91%E6%95%B0%E6%8D%AE%E7%BB%91%E5%AE%9A%E7%9A%84%E5%8E%9F%E7%90%86"><span class="toc-number">9.</span> <span class="toc-text">Vue 实现双向数据绑定的原理</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Proxy-%E7%9A%84%E4%BC%98%E7%82%B9%E7%BC%BA%E7%82%B9"><span class="toc-number">10.</span> <span class="toc-text">Proxy 的优点缺点</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6%E4%BC%A0%E5%8F%82"><span class="toc-number">11.</span> <span class="toc-text">父子组件传参</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%85%84%E5%BC%9F%E7%BB%84%E4%BB%B6%E4%BC%A0%E5%8F%82"><span class="toc-number">12.</span> <span class="toc-text">兄弟组件传参</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E8%B7%AF%E7%94%B1-hash-%E6%A8%A1%E5%BC%8F%E5%92%8C-history-%E6%A8%A1%E5%BC%8F"><span class="toc-number">13.</span> <span class="toc-text">vue 路由 hash 模式和 history 模式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%B7%AF%E7%94%B1%E5%AE%88%E5%8D%AB"><span class="toc-number">14.</span> <span class="toc-text">路由守卫</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%B7%AF%E7%94%B1%E4%BC%A0%E5%8F%82"><span class="toc-number">15.</span> <span class="toc-text">路由传参</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Vuex%EF%BC%88%E7%8A%B6%E6%80%81%E5%AD%98%E5%82%A8%EF%BC%89"><span class="toc-number">16.</span> <span class="toc-text">Vuex（状态存储）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8C%87%E4%BB%A4-directive"><span class="toc-number">17.</span> <span class="toc-text">vue 自定义指令 directive</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E8%BF%87%E6%BB%A4%E5%99%A8-filter"><span class="toc-number">18.</span> <span class="toc-text">vue 过滤器 filter</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#mixin-%E6%B3%A8%E5%85%A5"><span class="toc-number">19.</span> <span class="toc-text">mixin 注入</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#nextTick"><span class="toc-number">20.</span> <span class="toc-text">nextTick</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%99%9A%E6%8B%9F-DOM"><span class="toc-number">21.</span> <span class="toc-text">虚拟 DOM</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%88%B6%E5%AD%90%E5%AD%99%E7%BB%84%E4%BB%B6%E4%BC%A0%E5%8F%82"><span class="toc-number">22.</span> <span class="toc-text">父子孙组件传参</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AD%90%E7%BB%84%E4%BB%B6%E8%B0%83%E7%94%A8%E7%88%B6%E7%BB%84%E4%BB%B6%E6%96%B9%E6%B3%95-%E4%B8%8D%E7%94%A8%E5%B1%9E%E6%80%A7%E7%BB%91%E5%AE%9A%E7%9A%84%E6%96%B9%E5%BC%8F%E6%80%8E%E4%B9%88%E5%AE%9E%E7%8E%B0"><span class="toc-number">23.</span> <span class="toc-text">子组件调用父组件方法 不用属性绑定的方式怎么实现</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8A%A8%E6%80%81%E7%BB%91%E5%AE%9A%E4%BA%8B%E4%BB%B6"><span class="toc-number">24.</span> <span class="toc-text">动态绑定事件</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E6%89%93%E5%8C%85%E5%A4%9A%E9%A1%B5%E9%9D%A2-%E4%BC%98%E5%8C%96%E9%A6%96%E5%B1%8F%E5%8A%A0%E8%BD%BD"><span class="toc-number">25.</span> <span class="toc-text">vue 打包多页面 优化首屏加载</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#axios-%E7%9A%84%E5%B0%81%E8%A3%85"><span class="toc-number">26.</span> <span class="toc-text">axios 的封装</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-router-%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1"><span class="toc-number">27.</span> <span class="toc-text">vue-router 动态路由</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%8F%92%E6%A7%BD-slot"><span class="toc-number">28.</span> <span class="toc-text">插槽 slot</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E7%BB%84%E4%BB%B6%E6%9B%B4%E6%96%B0%E4%B9%8B%E5%90%8E%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%E6%9C%80%E6%96%B0-DOM"><span class="toc-number">29.</span> <span class="toc-text">vue 组件更新之后如何获取最新 DOM</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E5%8A%A8%E6%80%81%E7%BB%84%E4%BB%B6%E6%98%AF%E4%BB%80%E4%B9%88"><span class="toc-number">30.</span> <span class="toc-text">vue 动态组件是什么</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E5%A6%82%E4%BD%95%E5%BC%82%E6%AD%A5%E5%8A%A0%E8%BD%BD%E7%BB%84%E4%BB%B6"><span class="toc-number">31.</span> <span class="toc-text">vue 如何异步加载组件</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E5%A6%82%E4%BD%95%E7%BC%93%E5%AD%98%E7%BB%84%E4%BB%B6"><span class="toc-number">32.</span> <span class="toc-text">vue 如何缓存组件</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E7%BB%84%E4%BB%B6%E5%A6%82%E4%BD%95%E6%8A%BD%E7%A6%BB%E5%85%AC%E5%85%B1%E9%80%BB%E8%BE%91"><span class="toc-number">33.</span> <span class="toc-text">vue 组件如何抽离公共逻辑</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E6%98%AF%E5%A6%82%E4%BD%95%E7%9B%91%E5%90%AC%E6%95%B0%E7%BB%84%E5%8F%98%E5%8C%96%E7%9A%84"><span class="toc-number">34.</span> <span class="toc-text">vue 是如何监听数组变化的</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%99%9A%E6%8B%9F-DOM-diff-%E7%AE%97%E6%B3%95"><span class="toc-number">35.</span> <span class="toc-text">虚拟 DOM diff 算法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#vue-%E7%BB%84%E4%BB%B6%E6%98%AF%E5%A6%82%E4%BD%95%E6%B8%B2%E6%9F%93%E5%92%8C%E6%9B%B4%E6%96%B0%E7%9A%84"><span class="toc-number">36.</span> <span class="toc-text">vue 组件是如何渲染和更新的</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#v-for-%E4%B8%BA%E4%BD%95%E4%BD%BF%E7%94%A8-key"><span class="toc-number">37.</span> <span class="toc-text">v-for 为何使用 key</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6-data-%E4%B8%BA%E4%BD%95%E6%98%AF%E5%87%BD%E6%95%B0"><span class="toc-number">38.</span> <span class="toc-text">组件 data 为何是函数</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%95%E6%97%B6%E4%BD%BF%E7%94%A8-keep-alive"><span class="toc-number">39.</span> <span class="toc-text">何时使用 keep-alive</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%95%E6%97%B6%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8-beforeDestroy"><span class="toc-number">40.</span> <span class="toc-text">何时需要使用 beforeDestroy</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8-this-obj-%E7%BB%99-data-%E4%B8%AD%E6%96%B0%E5%8A%A0%E5%85%A5%E4%B8%80%E4%B8%AA%E5%B1%9E%E6%80%A7%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%95%B0%E6%8D%AE%E6%98%AF%E5%93%8D%E5%BA%94%E5%BC%8F%E7%9A%84%E4%B9%88%EF%BC%9F%E4%B8%BA%E4%BB%80%E4%B9%88%EF%BC%9F"><span class="toc-number">41.</span> <span class="toc-text">使用 this.obj&#x3D;{} 给 data 中新加入一个属性，这个数据是响应式的么？为什么？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#delete-%E5%92%8C-Vue-delete-%E5%88%A0%E9%99%A4%E6%95%B0%E7%BB%84%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="toc-number">42.</span> <span class="toc-text">delete 和 Vue.delete 删除数组的区别</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%A6%82%E4%BD%95%E4%BC%98%E5%8C%96-SPA-%E5%BA%94%E7%94%A8%E7%9A%84%E9%A6%96%E5%B1%8F%E5%8A%A0%E8%BD%BD%E9%80%9F%E5%BA%A6%E6%85%A2%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%9F"><span class="toc-number">43.</span> <span class="toc-text">如何优化 SPA 应用的首屏加载速度慢的问题？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%89%8D%E7%AB%AF%E5%A6%82%E4%BD%95%E4%BC%98%E5%8C%96%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD"><span class="toc-number">44.</span> <span class="toc-text">前端如何优化网站性能</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#query-%E5%92%8C-params-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="toc-number">45.</span> <span class="toc-text">query 和 params 的区别</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#SPA-%E5%8D%95%E9%A1%B5%E9%9D%A2%EF%BC%8C%E6%9C%89%E4%BB%80%E4%B9%88%E4%BC%98%E7%BC%BA%E7%82%B9%EF%BC%9F"><span class="toc-number">46.</span> <span class="toc-text">SPA 单页面，有什么优缺点？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%81%8A%E8%81%8A%E4%BD%A0%E5%AF%B9-Vue-js-%E7%9A%84-template-%E7%BC%96%E8%AF%91%E7%9A%84%E7%90%86%E8%A7%A3%EF%BC%9F"><span class="toc-number">47.</span> <span class="toc-text">聊聊你对 Vue.js 的 template 编译的理解？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%AC%AC%E4%B8%80%E6%AC%A1%E9%A1%B5%E9%9D%A2%E5%8A%A0%E8%BD%BD%E4%BC%9A%E8%A7%A6%E5%8F%91%E5%93%AA%E5%87%A0%E4%B8%AA%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%EF%BC%9F"><span class="toc-number">48.</span> <span class="toc-text">第一次页面加载会触发哪几个生命周期？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%87%BA%E7%8E%B0-vue-%E4%BF%AE%E6%94%B9%E6%95%B0%E6%8D%AE%E5%90%8E%E9%A1%B5%E9%9D%A2%E6%B2%A1%E6%9C%89%E5%88%B7%E6%96%B0%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%9F%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3%EF%BC%9F"><span class="toc-number">49.</span> <span class="toc-text">为什么会出现 vue 修改数据后页面没有刷新这个问题？如何解决？</span></a></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/blog/2023/03/18/React%E6%A8%A1%E6%8B%9F%E7%A7%BB%E5%85%A5title%E6%8F%90%E7%A4%BA/" title="React模拟移入title提示"><img src="/blog/2023/03/18/React%E6%A8%A1%E6%8B%9F%E7%A7%BB%E5%85%A5title%E6%8F%90%E7%A4%BA/react-logo.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="React模拟移入title提示"/></a><div class="content"><a class="title" href="/blog/2023/03/18/React%E6%A8%A1%E6%8B%9F%E7%A7%BB%E5%85%A5title%E6%8F%90%E7%A4%BA/" title="React模拟移入title提示">React模拟移入title提示</a><time datetime="2023-03-18T14:58:49.000Z" title="发表于 2023-03-18 22:58:49">2023-03-18</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2023/03/08/React%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6%E6%9C%89%E5%93%AA%E4%BA%9B%E4%BC%98%E7%82%B9%E5%92%8C%E7%BC%BA%E7%82%B9/" title="React高阶组件有哪些优点和缺点"><img src="/blog/2023/03/08/React%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6%E6%9C%89%E5%93%AA%E4%BA%9B%E4%BC%98%E7%82%B9%E5%92%8C%E7%BC%BA%E7%82%B9/react-logo.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="React高阶组件有哪些优点和缺点"/></a><div class="content"><a class="title" href="/blog/2023/03/08/React%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6%E6%9C%89%E5%93%AA%E4%BA%9B%E4%BC%98%E7%82%B9%E5%92%8C%E7%BC%BA%E7%82%B9/" title="React高阶组件有哪些优点和缺点">React高阶组件有哪些优点和缺点</a><time datetime="2023-03-08T14:58:49.000Z" title="发表于 2023-03-08 22:58:49">2023-03-08</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/08/02/useContext%E6%A8%A1%E6%8B%9Fredux/" title="useContext模拟redux"><img src="/blog/2022/08/02/useContext%E6%A8%A1%E6%8B%9Fredux/react-logo.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="useContext模拟redux"/></a><div class="content"><a class="title" href="/blog/2022/08/02/useContext%E6%A8%A1%E6%8B%9Fredux/" title="useContext模拟redux">useContext模拟redux</a><time datetime="2022-08-02T14:58:49.000Z" title="发表于 2022-08-02 22:58:49">2022-08-02</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/07/13/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E9%9D%A2%E8%AF%95%E9%A2%98/" title="小程序面试题"><img src="/blog/2022/07/13/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E9%9D%A2%E8%AF%95%E9%A2%98/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%9B%BE%E6%A0%87.jpeg" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="小程序面试题"/></a><div class="content"><a class="title" href="/blog/2022/07/13/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E9%9D%A2%E8%AF%95%E9%A2%98/" title="小程序面试题">小程序面试题</a><time datetime="2022-07-13T15:39:09.000Z" title="发表于 2022-07-13 23:39:09">2022-07-13</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/07/10/HTML%E5%92%8CCSS%E9%9D%A2%E8%AF%95%E9%A2%98/" title="HTML和CSS面试题"><img src="/blog/2022/07/10/HTML%E5%92%8CCSS%E9%9D%A2%E8%AF%95%E9%A2%98/csslogo.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="HTML和CSS面试题"/></a><div class="content"><a class="title" href="/blog/2022/07/10/HTML%E5%92%8CCSS%E9%9D%A2%E8%AF%95%E9%A2%98/" title="HTML和CSS面试题">HTML和CSS面试题</a><time datetime="2022-07-10T14:22:28.000Z" title="发表于 2022-07-10 22:22:28">2022-07-10</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2024 By 破破</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/blog/js/utils.js?v=4.14.0-b3"></script><script src="/blog/js/main.js?v=4.14.0-b3"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.35/dist/fancybox/fancybox.umd.min.js"></script><div class="js-pjax"><script>(() => {
  const runMermaid = (ele) => {
    window.loadMermaid = true
    const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'default'

    Array.from(ele).forEach((item, index) => {
      const mermaidSrc = item.firstElementChild
      const mermaidThemeConfig = '%%{init:{ \'theme\':\'' + theme + '\'}}%%\n'
      const mermaidID = 'mermaid-' + index
      const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent

      const renderFn = mermaid.render(mermaidID, mermaidDefinition)

      const renderV10 = () => {
        renderFn.then(({svg}) => {
          mermaidSrc.insertAdjacentHTML('afterend', svg)
        })
      }

      const renderV9 = svg => {
        mermaidSrc.insertAdjacentHTML('afterend', svg)
      }

      typeof renderFn === 'string' ? renderV9(renderFn) : renderV10()
    })
  }

  const codeToMermaid = () => {
    const codeMermaidEle = document.querySelectorAll('pre > code.mermaid')
    if (codeMermaidEle.length === 0) return
    
    codeMermaidEle.forEach(ele => {
      const newEle = document.createElement('div')
      newEle.className = 'mermaid-wrap'
      newEle.innerHTML = `<pre class="mermaid-src" hidden>${ele.textContent}</pre>`
      ele.parentNode.replaceWith(newEle)
    })
  }

  const loadMermaid = () => {
    if (false) codeToMermaid()
    const $mermaid = document.querySelectorAll('#article-container .mermaid-wrap')
    if ($mermaid.length === 0) return

    const runMermaidFn = () => runMermaid($mermaid)
    btf.addGlobalFn('themeChange', runMermaidFn, 'mermaid')
    window.loadMermaid ? runMermaidFn() : btf.getScript('https://cdn.jsdelivr.net/npm/mermaid@10.9.0/dist/mermaid.min.js').then(runMermaidFn)
  }
  
  btf.addGlobalFn('encrypt', loadMermaid, 'mermaid')
  window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid)
})()</script></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>